package com.wangwei.modules.utils.method.bean;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.springframework.ui.Model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wangwei.modules.servlet.spring.RequestMapping;
import com.wangwei.modules.servlet.spring.ResponseBody;
import com.wangwei.modules.servlet.spring.RestController;

public class MethodInfoVO {

    Object methodClass;

    RequestMapping requestMapping;

    Method method;

    List<ParameterVO> paras = new ArrayList<>();

    public MethodInfoVO() {
    }

    public MethodInfoVO(Method method) {
        this.method = method;
        RequestMapping[] rms = method.getAnnotationsByType(RequestMapping.class);
        if (rms != null && rms.length > 0) {
            requestMapping = rms[0];
        }

    }

    /**
     * 是否跳回页面
     * @return
     */
    public boolean isReturn2Page() {
        RestController c = method.getDeclaringClass().getAnnotation(RestController.class);
        ResponseBody r = method.getAnnotation(ResponseBody.class);
        return c == null && r == null;

        //不是restcontroller，没有ResponseBody

    }

    public String getPath() {
        String path = requestMapping.value();
        if (!path.startsWith("/")) {
            path = "/" + path;
        }
        return path;
    }

    @Override
    public String toString() {
        return method.getDeclaringClass().getName() + "." + method.getName() + "(" + paras + ")";
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public Object invoke(HashMap<String, String> paraMap, Model model) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
        Object[] args = new Object[paras.size()];
        for (int i = 0; i < paras.size(); i++) {
            ParameterVO pvo = paras.get(i);
            Class clazz=Class.forName( pvo.getType());
            if (clazz.isPrimitive()||"java.lang.String".equals(pvo.getType())||"java.lang.Integer".equals(pvo.getType())) {
                args[i] = parseType(paraMap.get(pvo.getName()), pvo.getType());
            }else  if ("org.springframework.ui.Model".equals(pvo.getType())) {
                args[i] = model;     
            }else{
                JSONObject json=(JSONObject) JSON.toJSON(paraMap);
                args[i] =json.toJavaObject(clazz);
            }
        }
        return method.invoke(methodClass, args);
    }

    Object parseType(Object value, String type) {
        if (value == null) {
            return null;
        }
        switch (type) {
        case "java.lang.String":
            return value.toString();
        case "java.lang.Integer":
            return Integer.parseInt(value.toString());
        default:
            return value;
        }
    }

    public MethodInfoVO addParas(String type, String name) {
        paras.add(new ParameterVO(type, name));
        return this;
    }

    public RequestMapping getRequestMapping() {
        return requestMapping;
    }

    public void setRequestMapping(RequestMapping requestMapping) {
        this.requestMapping = requestMapping;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public List<ParameterVO> getParas() {
        return paras;
    }

    public void setParas(List<ParameterVO> paras) {
        this.paras = paras;
    }

    public Object getMethodClass() {
        return methodClass;
    }

    public MethodInfoVO setMethodClass(Object methodClass) {
        this.methodClass = methodClass;
        return this;
    }

}
